package com.zenithmind.disk.pojo.domain;

import com.zenithmind.common.base.BaseEntity;
import com.zenithmind.disk.enums.FileStatus;
import com.zenithmind.disk.enums.FileType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

/**
 * 文件实体类
 * 遵循单一职责原则：专注于文件数据的表示和基本操作
 * 遵循开闭原则：通过枚举和方法封装，便于扩展
 */
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "存储用户文件信息实体", description = "存储用户文件信息实体")
public class Files extends BaseEntity {

    @Schema(description = "用户ID，关联users表")
    private String userId;

    @Schema(description = "父级文件夹ID，null表示根目录")
    private String parentId;

    @Schema(description = "文件名")
    private String fileName;

    @Schema(description = "文件类型，如txt、jpg等")
    private String fileType;

    @Schema(description = "文件大小，单位为字节")
    private Long fileSize;

    @Schema(description = "文件存储路径")
    private String filePath;

    @Schema(description = "是否为目录，0表示文件，1表示目录")
    private Integer isDirectory;

    @Schema(description = "文件的MD5值，用于校验文件完整性")
    private String fileMd5;

    @Schema(description = "文件状态，1正常，其他值表示已删除等")
    private Integer status;

    // ==================== 业务方法 ====================

    /**
     * 检查是否为目录
     * @return true如果是目录
     */
    public boolean isDirectory() {
        return isDirectory != null && isDirectory == 1;
    }

    /**
     * 检查是否为文件
     * @return true如果是文件
     */
    public boolean isFile() {
        return !isDirectory();
    }

    /**
     * 检查是否为根目录下的文件
     * @return true如果在根目录下
     */
    public boolean isInRootDirectory() {
        return StringUtils.isBlank(parentId);
    }

    /**
     * 获取文件状态枚举
     * @return 文件状态枚举
     */
    public FileStatus getFileStatus() {
        return FileStatus.fromCode(status);
    }

    /**
     * 设置文件状态
     * @param fileStatus 文件状态枚举
     */
    public void setFileStatus(FileStatus fileStatus) {
        this.status = fileStatus != null ? fileStatus.getCode() : null;
    }

    /**
     * 获取文件类型枚举
     * @return 文件类型枚举
     */
    public FileType getFileTypeEnum() {
        return FileType.fromCode(isDirectory);
    }

    /**
     * 设置文件类型
     * @param fileType 文件类型枚举
     */
    public void setFileTypeEnum(FileType fileType) {
        this.isDirectory = fileType != null ? fileType.getCode() : null;
    }

    /**
     * 检查文件是否正常状态
     * @return true如果文件状态正常
     */
    public boolean isNormal() {
        return getFileStatus().isNormal();
    }

    /**
     * 检查文件是否已删除
     * @return true如果文件已删除
     */
    public boolean isDeleted() {
        return getFileStatus().isDeleted();
    }

    /**
     * 获取文件扩展名
     * @return 文件扩展名，不包含点号
     */
    public String getFileExtension() {
        if (StringUtils.isBlank(fileName) || isDirectory()) {
            return "";
        }

        int lastDotIndex = fileName.lastIndexOf('.');
        return lastDotIndex > 0 ? fileName.substring(lastDotIndex + 1).toLowerCase() : "";
    }

    /**
     * 获取不包含扩展名的文件名
     * @return 不包含扩展名的文件名
     */
    public String getFileNameWithoutExtension() {
        if (StringUtils.isBlank(fileName)) {
            return "";
        }

        int lastDotIndex = fileName.lastIndexOf('.');
        return lastDotIndex > 0 ? fileName.substring(0, lastDotIndex) : fileName;
    }

    /**
     * 检查是否为图片文件
     * @return true如果是图片文件
     */
    public boolean isImageFile() {
        if (isDirectory()) {
            return false;
        }

        String extension = getFileExtension();
        return StringUtils.isNotBlank(extension) &&
               (extension.equals("jpg") || extension.equals("jpeg") ||
                extension.equals("png") || extension.equals("gif") ||
                extension.equals("bmp") || extension.equals("webp"));
    }

    /**
     * 检查是否为视频文件
     * @return true如果是视频文件
     */
    public boolean isVideoFile() {
        if (isDirectory()) {
            return false;
        }

        String extension = getFileExtension();
        return StringUtils.isNotBlank(extension) &&
               (extension.equals("mp4") || extension.equals("avi") ||
                extension.equals("mkv") || extension.equals("mov") ||
                extension.equals("wmv") || extension.equals("flv"));
    }

    /**
     * 检查是否为音频文件
     * @return true如果是音频文件
     */
    public boolean isAudioFile() {
        if (isDirectory()) {
            return false;
        }

        String extension = getFileExtension();
        return StringUtils.isNotBlank(extension) &&
               (extension.equals("mp3") || extension.equals("wav") ||
                extension.equals("flac") || extension.equals("aac") ||
                extension.equals("ogg") || extension.equals("wma"));
    }

    /**
     * 格式化文件大小为可读字符串
     * @return 格式化后的文件大小字符串
     */
    public String getFormattedFileSize() {
        if (fileSize == null || fileSize <= 0) {
            return "0 B";
        }

        String[] units = {"B", "KB", "MB", "GB", "TB"};
        double size = fileSize.doubleValue();
        int unitIndex = 0;

        while (size >= 1024 && unitIndex < units.length - 1) {
            size /= 1024;
            unitIndex++;
        }

        return String.format("%.2f %s", size, units[unitIndex]);
    }

    /**
     * 验证文件数据的完整性
     * @return true如果数据有效
     */
    public boolean isValid() {
        return StringUtils.isNotBlank(userId) &&
               StringUtils.isNotBlank(fileName) &&
               status != null &&
               isDirectory != null &&
               (isDirectory() || (fileSize != null && fileSize >= 0));
    }
}
